1 /*
2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021
3 License:   [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License].
4 Authors: Marcelo S. N. Mancini
5 
6 	Copyright Marcelo S. N. Mancini 2018 - 2021.
7 Distributed under the CC BY-4.0 License.
8    (See accompanying file LICENSE.txt or copy at
9 	https://creativecommons.org/licenses/by/4.0/
10 */
11 module hip.event.dispatcher;
12 private:
13     import hip.event.handlers.keyboard;
14     import hip.event.handlers.mouse;
15     import hip.systems.gamepad;
16     import hip.windowing.window;
17     import hip.api.config;
18 
19 public:
20     import hip.systems.input;
21     import hip.util.time;
22     import hip.api.input.keyboard;
23     import hip.api.input.button;
24     import hip.api.input.mouse;
25     import hip.api.input.gamepad;
26     import hip.api.renderer.viewport;
27     import hip.api.input.core : IHipInput;
28 
29 
30 
31 package __gshared HipGamepad[] gamepads;
32 
33 
34 /** 
35  * Class used to dispatch the events for the each specific handler.
36  *
37  *  In the entire engine, there must be only one dispatcher. But it is possible
38  *  to create more mouses and keyboards, but it is not being used yet.
39  */
40 class EventDispatcher : IHipInput
41 {
42     ulong frameCount;
43     KeyboardHandler keyboard = null;
44     HipMouse mouse = null;
45     HipWindow window;
46     bool* isInUpdate;
47     protected void delegate(uint width, uint height)[] resizeListeners;
48 
49     this(HipWindow window, bool* isInUpdate)
50     {
51         this.window = window;
52         this.isInUpdate = isInUpdate;
53         keyboard = new KeyboardHandler();
54         mouse = new HipMouse();
55         HipEventQueue.newController(); //Creates controller 0
56         initGamepads();
57         import hip.windowing.events;
58 
59         onKeyDown = (uint key)
60         {
61             try
62             {
63                 HipEventQueue.post(0, HipEventQueue.EventType.keyDown, HipEventQueue.Key(getHipKeyFromSystem(key)));
64             }
65             catch(Exception e){assert(false);}
66         };
67         onKeyUp = (uint key)
68         {
69             try{HipEventQueue.post(0, HipEventQueue.EventType.keyUp, HipEventQueue.Key(getHipKeyFromSystem(key)));}
70             catch(Exception e){assert(false);}
71         };
72         onMouseMove = (int x, int y)
73         {
74             try{HipEventQueue.post(0, HipEventQueue.EventType.touchMove, HipEventQueue.Touch(0, x, y));}
75             catch(Exception e){assert(false);}
76         };
77         onMouseUp = (ubyte btn, int x, int y)
78         {
79             try{HipEventQueue.post(0, HipEventQueue.EventType.touchUp, HipEventQueue.Touch(0, x, y));}
80             catch(Exception e){assert(false);}
81         };
82         onMouseDown = (ubyte btn, int x, int y)
83         {
84             try{HipEventQueue.post(0, HipEventQueue.EventType.touchDown, HipEventQueue.Touch(0, x, y));}
85             catch(Exception e){assert(false);}
86         };
87         onMouseWheel = (int moveX, int moveY)
88         {
89             try{HipEventQueue.post(0, HipEventQueue.EventType.touchScroll, HipEventQueue.Scroll(moveX, moveY, 0));}
90             catch(Exception e){assert(false);}
91         };
92 
93         onWindowResize = (uint width, uint height)
94         {
95             try{HipEventQueue.post(0, HipEventQueue.EventType.windowResize, HipEventQueue.Resize(width, height));}
96             catch(Exception e){assert(false);}
97         };
98         onWindowClosed = ()
99         {
100             try{HipEventQueue.post(0, HipEventQueue.EventType.exit, true);}
101             catch(Exception e){assert(false);}
102         };
103 
104     }
105     
106     bool hasQuit = false;
107 
108     final void errUpdateOnly(string name)
109     {
110         // debug
111         {
112             import hip.console.log;
113             bool inUpdate = *isInUpdate;
114             if(!inUpdate)
115                 loglnError("API ", name, " can only be used inside update()");
116         }
117     }
118 
119     void handleEvent()
120     {
121         window.pollWindowEvents();
122         handleHipEvent();
123         frameCount++;
124     }
125 
126 
127     void handleHipEvent()
128     {
129         
130         //Now poll the cross platform input queue
131         HipEventQueue.InputEvent* ev;
132         while((ev = HipEventQueue.poll(0)) != null)
133         {
134             switch(ev.type)
135             {
136                 case HipEventQueue.EventType.windowResize:
137                     auto w = ev.get!(HipEventQueue.Resize);
138                     foreach(r; resizeListeners)
139                         r(w.width, w.height);
140                     break;
141                 case HipEventQueue.EventType.touchDown:
142                     auto t = ev.get!(HipEventQueue.Touch);
143                     mouse.setPosition(t.xPos, t.yPos, t.id);
144                     mouse.setPressed(HipMouseButton.left, true);
145                     break;
146                 case HipEventQueue.EventType.touchUp:
147                     auto t = ev.get!(HipEventQueue.Touch);
148                     mouse.setPosition(t.xPos, t.yPos, t.id);
149                     mouse.setPressed(HipMouseButton.left, false);
150                     break;
151                 case HipEventQueue.EventType.touchMove:
152                     auto t = ev.get!(HipEventQueue.Touch);
153                     mouse.setPosition(t.xPos, t.yPos, t.id);
154                     break;
155                 case HipEventQueue.EventType.touchScroll:
156                     auto t = ev.get!(HipEventQueue.Scroll);
157                     mouse.setScroll(t.x, t.y, t.z);
158                     break;
159                 case HipEventQueue.EventType.keyDown:
160                 import hip.console.log;
161                     auto k = ev.get!(HipEventQueue.Key);
162                     keyboard.handleKeyDown(cast(HipKey)(k.id));
163                     break;
164                 case HipEventQueue.EventType.keyUp:
165                     auto k = ev.get!(HipEventQueue.Key);
166                     keyboard.handleKeyUp(cast(HipKey)(k.id));
167                     break;
168                 case HipEventQueue.EventType.gamepadConnected:
169                     import hip.console.log;rawlog("Gamepad connected");
170                     auto g = ev.get!(HipEventQueue.Gamepad);
171                     if(g.id+1 > gamepads.length)
172                         gamepads~= getNewGamepad(g.type);
173                     gamepads[g.id].setConnected(true);
174                     break;
175                 case HipEventQueue.EventType.gamepadDisconnected:
176                     import hip.console.log;rawlog("Gamepad disconnected");
177                     auto g = ev.get!(HipEventQueue.Gamepad);
178                     gamepads[g.id].setConnected(false);
179                     break;
180                 case HipEventQueue.EventType.exit:
181                     hasQuit = true;
182                     break;
183                 default:break;
184             }
185         }
186         
187         keyboard.update();
188     }
189     void pollGamepads(float deltaTime)
190     {
191         foreach (g; gamepads)
192             g.poll(deltaTime);
193     }
194 
195     void addOnResizeListener(void delegate(uint width, uint height) onResize)
196     in{assert(onResize !is null, "onResize event must not be null.");}
197     do
198     {
199         resizeListeners~= onResize;    
200     }
201 
202     ///Public API
203     float[2] getTouchPosition(uint id = 0){return cast(float[2])mouse.getPosition(id);}
204     float[2] getTouchDeltaPosition(uint id = 0){return cast(float[2])mouse.getDeltaPosition(id);}
205 
206     float[2] getNormallizedTouchPosition(uint id=0) 
207     {
208         import hip.hiprenderer;
209         float[2] ret = cast(float[2])getTouchPosition(id);
210         ret[0]/= HipRenderer.width;
211         ret[1]/= HipRenderer.height;
212         return ret;
213     }
214 
215     float[2] getWorldTouchPosition(uint id=0, Viewport vp = null) 
216     {
217         import hip.math.utils:clamp;
218         import hip.api.renderer.core;
219         float[2] ret = cast(float[2])getTouchPosition(id);
220         if(vp is null)
221             vp = HipRenderer.getCurrentViewport();
222 
223         ret[0] = clamp(((ret[0] - vp.x) / vp.width) * vp.worldWidth, 0, vp.worldWidth);
224         ret[1] = clamp(((ret[1] - vp.y) / vp.height) * vp.worldHeight, 0, vp.worldHeight);
225         
226 
227         return ret;
228     }
229     ubyte getMulticlickCount(HipMouseButton btn = HipMouseButton.any, uint id = 0)
230     {
231         errUpdateOnly("getMulticlickCount");
232         return mouse.getMulticlickCount(btn);
233     }
234     bool isDoubleClicked(HipMouseButton btn = HipMouseButton.any, uint id = 0)
235     {
236         errUpdateOnly("isDoubleClicked");
237         return mouse.isDoubleClicked(btn);
238     }
239     bool isMouseButtonPressed(HipMouseButton btn = HipMouseButton.any, uint id = 0)
240     {
241         errUpdateOnly("isMouseButtonPressed");
242         return mouse.isPressed(btn);
243     }
244     bool isMouseButtonJustPressed(HipMouseButton btn = HipMouseButton.any, uint id = 0)
245     {
246         errUpdateOnly("isMouseButtonJustPressed");
247         return mouse.isJustPressed(btn);
248     }
249     bool isMouseButtonJustReleased(HipMouseButton btn = HipMouseButton.any, uint id = 0)
250     {
251         errUpdateOnly("isMouseButtonJustReleased");
252         return mouse.isJustReleased(btn);
253     }
254     float[3] getScroll(uint id = 0){return cast(float[3])mouse.getScroll();}
255     bool isKeyPressed(char key, uint id = 0){return keyboard.isKeyPressed(key.toUppercase);}
256     bool isKeyJustPressed(char key, uint id = 0)
257     {
258         errUpdateOnly("isKeyJustPressed");
259         return keyboard.isKeyJustPressed(key.toUppercase);
260     }
261     bool isKeyJustReleased(char key, uint id = 0)
262     {
263         errUpdateOnly("isKeyJustReleased");
264         return keyboard.isKeyJustReleased(key.toUppercase);
265     }
266     float getKeyDownTime(char key, uint id = 0)
267     {
268         errUpdateOnly("getKeyDownTime");
269         return keyboard.getKeyDownTime(key.toUppercase);
270     }
271     float getKeyUpTime(char key, uint id = 0)
272     {
273         errUpdateOnly("getKeyUpTime");
274         return keyboard.getKeyUpTime(key.toUppercase);
275     }
276     ubyte getGamepadCount(){return cast(ubyte)gamepads.length;}
277     AHipGamepad getGamepad(ubyte id)
278     {
279         if(id >= gamepads.length)return null;
280         return gamepads[id];
281     }
282     float[3] getAnalog(HipGamepadAnalogs analog, ubyte id = 0)
283     {
284         if(id >= gamepads.length) return cast(float[3])Vector3.zero;
285         return cast(float[3])gamepads[id].getAnalogState(analog);
286     }
287     bool isGamepadButtonPressed(HipGamepadButton btn, ubyte id = 0)
288     {
289         if(id >= gamepads.length) return false;
290         return gamepads[id].isButtonPressed(btn);
291     }
292     bool isGamepadButtonJustPressed(HipGamepadButton btn, ubyte id = 0)
293     {
294         if(id >= gamepads.length) return false;
295         errUpdateOnly("isGamepadButtonJustPressed");
296         return gamepads[id].isButtonJustPressed(btn);
297     }
298     bool isGamepadButtonJustReleased(HipGamepadButton btn, ubyte id = 0)
299     {
300         if(id >= gamepads.length) return false;
301         errUpdateOnly("isGamepadButtonJustReleased");
302         return gamepads[id].isButtonJustReleased(btn);
303     }
304 
305     bool areGamepadButtonsPressed(scope HipGamepadButton[] btns, ubyte id = 0)
306     {
307         if(id >= gamepads.length) return false;
308         errUpdateOnly("areGamepadButtonsPressed");
309         return gamepads[id].areButtonsPressed(btns);
310     }
311     bool areGamepadButtonsJustPressed(scope HipGamepadButton[] btns, ubyte id = 0)
312     {
313         if(id >= gamepads.length) return false;
314         errUpdateOnly("areGamepadButtonsJustPressed");
315         return gamepads[id].areButtonsJustPressed(btns);
316     }
317     bool areGamepadButtonsJustReleased(scope HipGamepadButton[] btns, ubyte id = 0)
318     {
319         if(id >= gamepads.length) return false;
320         errUpdateOnly("areGamepadButtonsJustReleased");
321         return gamepads[id].areButtonsJustReleased(btns);
322     }
323     
324     bool isGamepadWireless(ubyte id = 0)
325     {
326         if(id >= gamepads.length) return false;
327         return gamepads[id].isWireless();
328     }
329     bool setGamepadVibrating(float vibrationPower, float time, ubyte id = 0)
330     {
331         if(id >= gamepads.length) return false;
332         return gamepads[id].setVibrating(vibrationPower, time);
333     }
334     float getGamepadBatteryStatus(ubyte id = 0)
335     {
336         if(id >= gamepads.length) return 0;
337         return gamepads[id].getBatteryStatus();
338     }
339 
340     void postUpdate()
341     {
342         keyboard.postUpdate();
343         mouse.postUpdate();
344         foreach(g; gamepads)
345             g.postUpdate();
346     }
347 }
348 
349 
350 version(Windows)
351 {
352     public HipKey getHipKeyFromSystem(uint key)
353     {
354         import hip.windowing.platforms.winlib.keys;
355         ushort k = cast(ushort)(key);
356         assert(k > 0 && k <= ubyte.max, "Key out of range");
357         switch(k)
358         {
359             case VK_BACK: return HipKey.BACKSPACE;
360             case VK_TAB: return HipKey.TAB;
361             case VK_ESCAPE: return HipKey.ESCAPE;
362 
363 
364             case VK_SHIFT: return HipKey.SHIFT;
365             case VK_CONTROL: return HipKey.CTRL;
366             case VK_MENU: return HipKey.ALT;
367             case VK_SNAPSHOT: return HipKey.PRINT;
368             
369             case VK_RETURN: return HipKey.ENTER;
370             case VK_CAPITAL: return HipKey.CAPSLOCK;
371             case VK_SPACE: return HipKey.SPACE;
372             case VK_PRIOR: return HipKey.PAGE_UP;
373             case VK_NEXT: return HipKey.PAGE_UP;
374             case VK_END: return HipKey.END;
375             case VK_HOME: return HipKey.HOME;
376             case VK_LEFT: return HipKey.ARROW_LEFT;
377             case VK_UP: return HipKey.ARROW_UP;
378             case VK_RIGHT: return HipKey.ARROW_RIGHT;
379             case VK_DOWN: return HipKey.ARROW_DOWN;
380             case VK_INSERT: return HipKey.INSERT;
381             case VK_DELETE: return HipKey.DELETE;
382             //0
383             case 0x30: return HipKey._0;
384             case 0x31: return HipKey._1;
385             case 0x32: return HipKey._2;
386             case 0x33: return HipKey._3;
387             case 0x34: return HipKey._4;
388             case 0x35: return HipKey._5;
389             case 0x36: return HipKey._6;
390             case 0x37: return HipKey._7;
391             case 0x38: return HipKey._8;
392             case 0x39: return HipKey._9;
393             //A
394             case 0x41: return HipKey.A;
395             case 0x42: return HipKey.B;
396             case 0x43: return HipKey.C;
397             case 0x44: return HipKey.D;
398             case 0x45: return HipKey.E;
399             case 0x46: return HipKey.F;
400             case 0x47: return HipKey.G;
401             case 0x48: return HipKey.H;
402             case 0x49: return HipKey.I;
403             case 0x4A: return HipKey.J;
404             case 0x4B: return HipKey.K;
405             case 0x4C: return HipKey.L;
406             case 0x4D: return HipKey.M;
407             case 0x4E: return HipKey.N;
408             case 0x4F: return HipKey.O;
409             case 0x50: return HipKey.P;
410             case 0x51: return HipKey.Q;
411             case 0x52: return HipKey.R;
412             case 0x53: return HipKey.S;
413             case 0x54: return HipKey.T;
414             case 0x55: return HipKey.U;
415             case 0x56: return HipKey.V;
416             case 0x57: return HipKey.W;
417             case 0x58: return HipKey.X;
418             case 0x59: return HipKey.Y;
419             case 0x5A: return HipKey.Z;
420             case VK_LWIN: return HipKey.META_LEFT;
421             case VK_RWIN: return HipKey.META_RIGHT;
422             //Maybe there's a need to change?
423             case VK_NUMPAD0: return HipKey._0;
424             case VK_NUMPAD1: return HipKey._1;
425             case VK_NUMPAD2: return HipKey._2;
426             case VK_NUMPAD3: return HipKey._3;
427             case VK_NUMPAD4: return HipKey._4;
428             case VK_NUMPAD5: return HipKey._5;
429             case VK_NUMPAD6: return HipKey._6;
430             case VK_NUMPAD7: return HipKey._7;
431             case VK_NUMPAD8: return HipKey._8;
432             case VK_NUMPAD9: return HipKey._9;
433 
434             case VK_F1: return HipKey.F1;
435             case VK_F2: return HipKey.F2;
436             case VK_F3: return HipKey.F3;
437             case VK_F4: return HipKey.F4;
438             case VK_F5: return HipKey.F5;
439             case VK_F6: return HipKey.F6;
440             case VK_F7: return HipKey.F7;
441             case VK_F8: return HipKey.F8;
442             case VK_F9: return HipKey.F9;
443             case VK_F10: return HipKey.F10;
444             case VK_F11: return HipKey.F11;
445             case VK_F12: return HipKey.F12;
446 
447             case VK_LSHIFT: return HipKey.SHIFT;
448             case VK_RSHIFT: return HipKey.SHIFT;
449 
450             case VK_LCONTROL: return HipKey.CTRL;
451             case VK_RCONTROL: return HipKey.CTRL;
452             
453             case VK_LMENU: return HipKey.ALT;
454             case VK_RMENU: return HipKey.ALT;
455 
456             case VK_OEM_1: return HipKey.SEMICOLON;
457 
458             case VK_OEM_COMMA: return HipKey.COMMA;
459             case VK_OEM_MINUS: return HipKey.MINUS;
460             case VK_OEM_PERIOD: return HipKey.PERIOD;
461 
462             case VK_OEM_2: return HipKey.SLASH;
463             
464             case VK_OEM_4: return HipKey.BRACKET_LEFT;
465             case VK_OEM_5: return HipKey.BACKSLASH;
466             case VK_OEM_6: return HipKey.BRACKET_RIGHT;
467             case VK_OEM_7: return HipKey.QUOTE;
468             case  0xFF: return HipKey.NONE; //Invalid
469 
470             default:
471                 version(HipCheckUnknownKeycode)
472                 {
473                     import hip.util.conv:to;
474                     assert(false, "Unknown key received ("~to!string(k)~")");
475                 }
476                 else
477                     return cast(HipKey)k;
478         }
479     }
480 }
481 else static if(isLinuxPC)
482 {
483     public HipKey getHipKeyFromSystem(uint key)
484     {
485         import hip.windowing.platforms.x11lib.keysym;
486         switch(key)
487         {
488             case XK_BackSpace: return HipKey.BACKSPACE;
489             case XK_Tab: return HipKey.TAB;
490             case XK_Return: return HipKey.ENTER;
491             case XK_KP_Enter: return HipKey.ENTER;
492             case XK_Shift_L: return HipKey.SHIFT;
493             case XK_Shift_R: return HipKey.SHIFT;
494             case XK_Control_L: return HipKey.CTRL;
495             case XK_Control_R: return HipKey.CTRL;
496             case XK_Alt_L: return HipKey.ALT;
497             case XK_Alt_R: return HipKey.ALT;
498             case XK_Pause: return HipKey.PAUSE_BREAK;
499             case XK_Caps_Lock: return HipKey.CAPSLOCK;
500             case XK_Escape: return HipKey.ESCAPE;
501             case XK_space: return HipKey.SPACE;
502             case XK_Page_Up: return HipKey.PAGE_UP;
503             case XK_Page_Down: return HipKey.PAGE_DOWN;
504             case XK_End: return HipKey.END;
505             case XK_Home: return HipKey.HOME;
506             case XK_Left: return HipKey.ARROW_LEFT;
507             case XK_Up: return HipKey.ARROW_UP;
508             case XK_Right: return HipKey.ARROW_RIGHT;
509             case XK_Down: return HipKey.ARROW_DOWN;
510             case XK_Insert: return HipKey.INSERT;
511             case XK_Delete: return HipKey.DELETE;
512             case XK_0: return HipKey._0;
513             case XK_1: return HipKey._1;
514             case XK_2: return HipKey._2;
515             case XK_3: return HipKey._3;
516             case XK_4: return HipKey._4;
517             case XK_5: return HipKey._5;
518             case XK_6: return HipKey._6;
519             case XK_7: return HipKey._7;
520             case XK_8: return HipKey._8;
521             case XK_9: return HipKey._9;
522             case XK_A: return HipKey.A;
523             case XK_B: return HipKey.B;
524             case XK_C: return HipKey.C;
525             case XK_D: return HipKey.D;
526             case XK_E: return HipKey.E;
527             case XK_F: return HipKey.F;
528             case XK_G: return HipKey.G;
529             case XK_H: return HipKey.H;
530             case XK_I: return HipKey.I;
531             case XK_J: return HipKey.J;
532             case XK_K: return HipKey.K;
533             case XK_L: return HipKey.L;
534             case XK_M: return HipKey.M;
535             case XK_N: return HipKey.N;
536             case XK_O: return HipKey.O;
537             case XK_P: return HipKey.P;
538             case XK_Q: return HipKey.Q;
539             case XK_R: return HipKey.R;
540             case XK_S: return HipKey.S;
541             case XK_T: return HipKey.T;
542             case XK_U: return HipKey.U;
543             case XK_V: return HipKey.V;
544             case XK_W: return HipKey.W;
545             case XK_X: return HipKey.X;
546             case XK_Y: return HipKey.Y;
547             case XK_Z: return HipKey.Z;
548             case XK_a: return HipKey.A;
549             case XK_b: return HipKey.B;
550             case XK_c: return HipKey.C;
551             case XK_d: return HipKey.D;
552             case XK_e: return HipKey.E;
553             case XK_f: return HipKey.F;
554             case XK_g: return HipKey.G;
555             case XK_h: return HipKey.H;
556             case XK_i: return HipKey.I;
557             case XK_j: return HipKey.J;
558             case XK_k: return HipKey.K;
559             case XK_l: return HipKey.L;
560             case XK_m: return HipKey.M;
561             case XK_n: return HipKey.N;
562             case XK_o: return HipKey.O;
563             case XK_p: return HipKey.P;
564             case XK_q: return HipKey.Q;
565             case XK_r: return HipKey.R;
566             case XK_s: return HipKey.S;
567             case XK_t: return HipKey.T;
568             case XK_u: return HipKey.U;
569             case XK_v: return HipKey.V;
570             case XK_w: return HipKey.W;
571             case XK_x: return HipKey.X;
572             case XK_y: return HipKey.Y;
573             case XK_z: return HipKey.Z;
574             case XK_Meta_L: return HipKey.META_LEFT;
575             case XK_Meta_R: return HipKey.META_RIGHT;
576             case XK_F1: return HipKey.F1;
577             case XK_F2: return HipKey.F2;
578             case XK_F3: return HipKey.F3;
579             case XK_F4: return HipKey.F4;
580             case XK_F5: return HipKey.F5;
581             case XK_F6: return HipKey.F6;
582             case XK_F7: return HipKey.F7;
583             case XK_F8: return HipKey.F8;
584             case XK_F9: return HipKey.F9;
585             case XK_F10: return HipKey.F10;
586             case XK_F11: return HipKey.F11;
587             case XK_F12: return HipKey.F12;
588             case XK_semicolon: return HipKey.SEMICOLON;
589             case XK_equal: return HipKey.EQUAL;
590             case XK_comma: return HipKey.COMMA;
591             case XK_minus: return HipKey.MINUS;
592             case XK_period: return HipKey.PERIOD;
593             case XK_slash: return HipKey.SLASH;
594             case XK_bracketleft: return HipKey.BRACKET_LEFT;
595             case XK_bracketright: return HipKey.BRACKET_RIGHT;
596             case XK_backslash: return HipKey.BACKSLASH;
597             case XK_grave: return HipKey.QUOTE;
598             default:
599             {
600                 version(HipCheckUnknownKeycode)
601                 {
602                     import hip.util.conv:to;
603                     import hip.error.handler;
604                     ErrorHandler.assertExit(false, "Unknown key received ("~to!string(key)~")");
605                     return cast(HipKey)0;
606                 }
607                 else
608                     return cast(HipKey)key;
609             }
610         }
611     }
612 }
613 else version(WebAssembly)
614 {
615     public HipKey getHipKeyFromSystem(uint key)
616     {
617         ushort k = cast(ushort)(key);
618         assert(k > 0 && k <= ubyte.max, "Key out of range");
619         switch(k)
620         {
621             case 8: return HipKey.BACKSPACE;
622             case 9: return HipKey.TAB;
623             case 27: return HipKey.ESCAPE;
624 
625             
626             case 13: return HipKey.ENTER;
627             case 20: return HipKey.CAPSLOCK;
628             case 32: return HipKey.SPACE;
629             case 33: return HipKey.PAGE_UP;
630             case 35: return HipKey.END;
631             case 36: return HipKey.HOME;
632             case 37: return HipKey.ARROW_LEFT;
633             case 38: return HipKey.ARROW_UP;
634             case 39: return HipKey.ARROW_RIGHT;
635             case 40: return HipKey.ARROW_DOWN;
636             case 45: return HipKey.INSERT;
637             case 46: return HipKey.DELETE;
638             //0
639             case 48: return HipKey._0;
640             case 49: return HipKey._1;
641             case 50: return HipKey._2;
642             case 51: return HipKey._3;
643             case 52: return HipKey._4;
644             case 53: return HipKey._5;
645             case 54: return HipKey._6;
646             case 55: return HipKey._7;
647             case 56: return HipKey._8;
648             case 57: return HipKey._9;
649             //A
650             case 65: return HipKey.A;
651             case 66: return HipKey.B;
652             case 67: return HipKey.C;
653             case 68: return HipKey.D;
654             case 69: return HipKey.E;
655             case 70: return HipKey.F;
656             case 71: return HipKey.G;
657             case 72: return HipKey.H;
658             case 73: return HipKey.I;
659             case 74: return HipKey.J;
660             case 75: return HipKey.K;
661             case 76: return HipKey.L;
662             case 77: return HipKey.M;
663             case 78: return HipKey.N;
664             case 79: return HipKey.O;
665             case 80: return HipKey.P;
666             case 81: return HipKey.Q;
667             case 82: return HipKey.R;
668             case 83: return HipKey.S;
669             case 84: return HipKey.T;
670             case 85: return HipKey.U;
671             case 86: return HipKey.V;
672             case 87: return HipKey.W;
673             case 88: return HipKey.X;
674             case 89: return HipKey.Y;
675             case 90: return HipKey.Z;
676             case 91: return HipKey.META_LEFT;
677             case 93: return HipKey.META_RIGHT;
678             //Maybe there's a need to change?
679             case 97: return HipKey._0;
680             case 98: return HipKey._1;
681             case 99: return HipKey._2;
682             case 100: return HipKey._3;
683             case 101: return HipKey._4;
684             case 102: return HipKey._5;
685             case 103: return HipKey._6;
686             case 104: return HipKey._7;
687             case 105: return HipKey._8;
688             case 106: return HipKey._9;
689 
690             case 112: return HipKey.F1;
691             case 113: return HipKey.F2;
692             case 114: return HipKey.F3;
693             case 115: return HipKey.F4;
694             case 116: return HipKey.F5;
695             case 117: return HipKey.F6;
696             case 118: return HipKey.F7;
697             case 119: return HipKey.F8;
698             case 120: return HipKey.F9;
699             case 121: return HipKey.F10;
700             case 122: return HipKey.F11;
701             case 123: return HipKey.F12;
702 
703             case 16: return HipKey.SHIFT;
704             case 17: return HipKey.CTRL;
705             case 18: return HipKey.ALT;
706 
707             case 191: return HipKey.SEMICOLON;
708 
709             case 188: return HipKey.COMMA;
710             case 189: return HipKey.MINUS;
711             case 190: return HipKey.PERIOD;
712 
713             case 193: return HipKey.SLASH;
714             
715             case 221: return HipKey.BRACKET_LEFT;
716             case 220: return HipKey.BRACKET_RIGHT;
717             case 226: return HipKey.BACKSLASH;
718             case 192: return HipKey.QUOTE;
719             case  0xFF: return HipKey.NONE; //Invalid
720 
721             default:
722                 version(HipCheckUnknownKeycode)
723                 {
724                     import hip.util.conv:to;
725                     assert(false, "Unknown key received ("~to!string(k)~")");
726                 }
727                 else
728                     return cast(HipKey)k;
729         }
730     }
731 }
732 else version(AppleOS)
733 {
734     public HipKey getHipKeyFromSystem(uint key)
735     {
736         switch(key)
737         {
738 
739             //Special Chars
740             case  0x31: return HipKey.SPACE; //space
741             case  0x24: return HipKey.ENTER; //returnKey
742             case  0x4C: return HipKey.ENTER; //enterKey
743             case  0x35: return HipKey.ESCAPE; //escape
744             case  0x38: return HipKey.SHIFT; //shift
745             case  0x37: return HipKey.ALT; //command
746             
747             //DPad Keys
748             case  0x7B: return HipKey.ARROW_LEFT; //leftArrow
749             case  0x7C: return HipKey.ARROW_RIGHT; //rightArrow
750             case  0x7D: return HipKey.ARROW_DOWN; //downArrow
751             case  0x7E: return HipKey.ARROW_UP; //upArrow
752             
753             //Alphabet
754             case  0x00: return HipKey.A; //a
755             case  0x0B: return HipKey.B; //b
756             case  0x08: return HipKey.C; //c
757             case  0x02: return HipKey.D; //d
758             case  0x0E: return HipKey.E; //e
759             case  0x03: return HipKey.F; //f
760             case  0x05: return HipKey.G; //g
761             case  0x04: return HipKey.H; //h
762             case  0x22: return HipKey.I; //i
763             case  0x26: return HipKey.J; //j
764             case  0x28: return HipKey.K; //k
765             case  0x25: return HipKey.L; //l
766             case  0x2E: return HipKey.M; //m
767             case  0x2D: return HipKey.N; //n
768             case  0x1F: return HipKey.O; //o
769             case  0x23: return HipKey.P; //p
770             case  0x0C: return HipKey.Q; //q
771             case  0x0F: return HipKey.R; //r
772             case  0x01: return HipKey.S; //s
773             case  0x11: return HipKey.T; //t
774             case  0x20: return HipKey.U; //u
775             case  0x09: return HipKey.V; //v
776             case  0x0D: return HipKey.W; //w
777             case  0x07: return HipKey.X; //x
778             case  0x10: return HipKey.Y; //y
779             case  0x06: return HipKey.Z; //z
780             
781             //Top Numbers
782             case  0x1D: return HipKey._0;//zero
783             case  0x12: return HipKey._1; //one
784             case  0x13: return HipKey._2;//two
785             case  0x14: return HipKey._3;//three
786             case  0x15: return HipKey._4;//four
787             case  0x17: return HipKey._5;//five
788             case  0x16: return HipKey._6;//six
789             case  0x1A: return HipKey._7;//seven
790             case  0x1C: return HipKey._8;//eight
791             case  0x19: return HipKey._9;//nine
792             
793             //Keypad Numbers
794             case  0x52: return HipKey._0; //keypad0
795             case  0x53: return HipKey._1; //keypad1
796             case  0x54: return HipKey._2; //keypad2
797             case  0x55: return HipKey._3; //keypad3
798             case  0x56: return HipKey._4; //keypad4
799             case  0x57: return HipKey._5; //keypad5
800             case  0x58: return HipKey._6; //keypad6
801             case  0x59: return HipKey._7; //keypad7
802             case  0x5B: return HipKey._8; //keypad8
803             case  0x5C: return HipKey._9; //keypad9
804             case  0xFF: return HipKey.NONE; //Invalid
805             default:
806                 // version(HipCheckUnknownKeycode)
807                 // {
808                 //     import hip.console.log;
809                 //     loglnError("Unknown key received ("~to!string(k)~")");
810                 //     assert(false, "Unknown key received ("~to!string(k)~")");
811                 // }
812                 // else
813                     return cast(HipKey)key;
814 
815         }
816     }
817 }
818 else version(PSVita)
819 {
820     public HipKey getHipKeyFromSystem(uint key){return HipKey._0;}
821 }
822 else public HipKey getHipKeyFromSystem(uint key){return HipKey._0;}
823